package com.service;

import static com.def.GenericDef.*;

import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;
import org.hibernate.LockMode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import com.dao.IBisPamDao;
import com.dao.IRetBoxDao;
import com.dao.IRetPrdInfoDao;
import com.icim.service.ICIMBaseService;
import com.model.Ret_box;
import com.model.Ret_prd_info;
import com.rtnBean.NotFoundRtnBeen;
import com.rtnBean.SimpleRtnBeen;
import com.tx.Xpcnpnlout.XpcnpnloutI;
import com.tx.Xpcnpnlout.XpcnpnloutO;
import com.util.GUIDGenerator;
import com.util.MqOpe;
import com.util.Util;

@Scope("prototype")
@Service("XpcnpnloutService")
public class XpcnpnloutService extends ICIMBaseService{
	private static Logger logger = Logger.getLogger(XpcnpnloutService.class);
	private static String TX_NAME = T_XPCNPNLOUT;

	private XpcnpnloutI inTrx;
	private XpcnpnloutO outTrx;
	private MqOpe mqOpe;

	private String gszMsgBuf = "";
	private Timestamp gEvtTimestamp;
	private Double gEvtTimeD;
	private String gEvtSeqID;

	@Autowired
	private IRetBoxDao retBoxDao;
	@Autowired
	private IRetPrdInfoDao retPrdInfoDao;
	@Autowired
	private IBisPamDao bisPamdao;
	public String subMainProc(String strInMsg) {
		long rtnCode = _NORMAL;

		String outMsg = null;
		gszMsgBuf = "";
		gEvtTimestamp = Util.getCurrentTimestamp();
		gEvtTimeD = Util.getDoubleTime();
		gEvtSeqID = GUIDGenerator.javaGUID();
		inTrx = new XpcnpnloutI();
		outTrx = new XpcnpnloutO();
		outTrx.setTrx_id(TX_NAME);
		outTrx.setType_id(TRX_OUT);
		outTrx.setRtn_code(RETURN_CODE_SET_ERROR);
		mqOpe = new MqOpe();

		try {
			inTrx = (XpcnpnloutI) mqOpe.inStr2Obj(strInMsg, inTrx);
			logger.info("InTrx is " + strInMsg);

			rtnCode = subMainProc2();
			if (rtnCode != _NORMAL) {
				TransactionAspectSupport.currentTransactionStatus()
						.setRollbackOnly();
				outTrx.setRtn_code(String.valueOf(rtnCode));
				outTrx.setRtn_mesg(gszMsgBuf);
			} else {
				outTrx.setRtn_code(String.valueOf(RETURN_CODE_OK));
				outTrx.setRtn_mesg(RETURN_MESG_OK);
				retPrdInfoDao.flushCurSession();
			}
		} catch (Exception ex) {
			TransactionAspectSupport.currentTransactionStatus()
					.setRollbackOnly();
			outTrx.setRtn_mesg(ex.toString());
			outTrx.setRtn_code(RETURN_CODE_UNKNOWN);
			logger.error(Util.stackTraceToString(ex));
		} finally {
			outMsg = mqOpe.obj2Str(outTrx);
			return outMsg;
		}
	}

	/**
	 * Check inTrx items
	 * 
	 * @return
	 */
	private long checkInTtx() {
		long rtnCode = _NORMAL;

		if (null == inTrx.getPnl_cnt() || 0 >= inTrx.getPnl_cnt()) {
			gszMsgBuf = "产品取消转入的数量为 [" + inTrx.getPnl_cnt() + "],无效!";
			return E_XPCNPNLOUT_INPUT_ITEM_EMPT;
		}

		return rtnCode;
	}

	/**
	 * All move in logic
	 * 
	 * @return
	 */
	private long subMainProc2() {
		long rtnCode = _NORMAL;
		SimpleRtnBeen rtnBeen = new SimpleRtnBeen(_NORMAL);
		Ret_box ret_box = new Ret_box();
		List<Ret_prd_info> gRet_prd_infoList = new ArrayList<Ret_prd_info>();

		// Check inTrx items
		rtnCode = checkInTtx();
		if (rtnCode != _NORMAL) {
			return rtnCode;
		}

		// Check sht & Save judge info
		rtnBeen = checkRetPrdInfo();
		if (rtnBeen.getlRc() != _NORMAL) {
			return rtnBeen.getlRc();
		} else {
			gRet_prd_infoList = (List<Ret_prd_info>) rtnBeen.getObj();
		}

		// Check box
		rtnBeen = checkRetBox(gRet_prd_infoList);
		if (rtnBeen.getlRc() != _NORMAL) {
			return rtnBeen.getlRc();
		} else {
			ret_box = (Ret_box) rtnBeen.getObj();
		}
		
		// Update prd info -> into box
		rtnBeen = updateRetPrdInfoAndBoxInfo(gRet_prd_infoList, ret_box);
		if (rtnBeen.getlRc() != _NORMAL) {
			return rtnBeen.getlRc();
		}

		// TODO mtrlBoxCheck
		rtnCode = getPrdMode(ret_box.getBox_id());
		if (rtnCode != _NORMAL) {
			return rtnCode;
		}
		return rtnCode;
	}

	/**
	 * Update prd info -> into box
	 * 
	 * @return
	 */
	private SimpleRtnBeen updateRetPrdInfoAndBoxInfo(
			List<Ret_prd_info> ret_prd_infoList, Ret_box ret_box) {
		if (ret_prd_infoList.isEmpty()) {
			gszMsgBuf = "No prd in inMsg, should not happen!";
			return new SimpleRtnBeen(E_XPPNLOUT_PRD_LIST_NULL);
		}
	   //更新产品信息 
        for(Integer prdCnt = 0; prdCnt < ret_prd_infoList.size(); prdCnt++){
    		ret_prd_infoList.get(prdCnt).setBox_id_fk(_SPACE0);
    		ret_prd_infoList.get(prdCnt).setP2_timestamp(null);
    		ret_prd_infoList.get(prdCnt).setEvt_cate(EVT_PNL_CANCEL_MOVE);
//    		ret_prd_infoList.get(prdCnt).setEvt_usr(inTrx.getEvt_usr());
    		ret_prd_infoList.get(prdCnt).setEvt_timestamp(gEvtTimestamp);
    		ret_prd_infoList.get(prdCnt).setEvt_time_d(gEvtTimeD);
    		ret_prd_infoList.get(prdCnt).setEvt_seq_id(gEvtSeqID);
//    		ret_prd_infoList.get(prdCnt).setMtrl_slot_no_fk(null);
    		retPrdInfoDao.update(ret_prd_infoList.get(prdCnt));
        }
       //更新箱子信息 		
		ret_box.setPrd_qty(ret_box.getPrd_qty() - ret_prd_infoList.size());
		if (ret_box.getPrd_qty() == 0) {
			ret_box.setReal_emp(EMPTY_CARRIER);
		}
		
		ret_box.setWo_id_fk(_SPACE);
		ret_box.setMdl_id_fk(_SPACE);
		ret_box.setMdl_typ_fk(_SPACE);
		ret_box.setMdl_cate_fk(_SPACE);
		
		retBoxDao.update(ret_box);

		outTrx.setWo_id(ret_prd_infoList.get(0).getWo_id_fk());
		outTrx.setBox_id(ret_box.getBox_id());
		outTrx.setPrd_qty(ret_box.getPrd_qty().toString());
		outTrx.setEvt_user(inTrx.getEvt_usr());
		outTrx.setEvt_timestamp(gEvtTimestamp);

		return new SimpleRtnBeen(_NORMAL);
	}

	/**
	 * Get & chk & set prd info
	 * 
	 * @return
	 */
	private SimpleRtnBeen checkRetPrdInfo() {
		SimpleRtnBeen rtnBeen = new SimpleRtnBeen(_NORMAL);
		List<Ret_prd_info> ret_prd_infoList = new ArrayList<Ret_prd_info>();

		for (int i = 0; i < inTrx.getPnl_cnt(); i++) {
			Ret_prd_info ret_prd_info = new Ret_prd_info();
			ret_prd_info = retPrdInfoDao.get(inTrx.getIary().get(i)
					.getPrd_seq_id());
			if (null == ret_prd_info) {
				gszMsgBuf = new NotFoundRtnBeen(inTrx.getIary().get(i)
						.getPrd_seq_id(), Ret_prd_info.class).toString();
				return new SimpleRtnBeen(E_RET_PRD_INFO + E_READ_NOT_FOUND);
			}

			// Must INPR
			if (!PROC_IN_PROCESS.equals(ret_prd_info.getPrd_stat())) {
				gszMsgBuf = "状态为 [" + ret_prd_info.getPrd_stat()
						+ "] ,必须为 [" + PROC_IN_PROCESS + "]";
				return new SimpleRtnBeen(E_XPCNPNLOUT_INVALIED_PRD_STAT);
			}

			if (WIP_REATIN.equals(ret_prd_info.getBnk_flg())) {
				gszMsgBuf = "产品的bnk_flg为 [" + ret_prd_info.getBnk_flg()
					+ "],已在制保留，请先取消在制保留！";
				return new SimpleRtnBeen(E_XPCNPNLOUT_INVALIED_BNK_FLG);
			}
			
			// Box ID must space
			if (Util.isSpaceCheck(ret_prd_info.getBox_id_fk())) {
				gszMsgBuf = "产品 [" + ret_prd_info.getPrd_seq_id()
						+ "] 未转入任何箱子，请确认";
				return new SimpleRtnBeen(E_XPCNPNLOUT_PRD_NOT_IN_BOX);
			}
			ret_prd_infoList.add(ret_prd_info);
		}

		return new SimpleRtnBeen(ret_prd_infoList);
	}

	/**
	 * Get & chk box info
	 * 
	 * @param boxId
	 * @return
	 */
	private SimpleRtnBeen checkRetBox(List<Ret_prd_info> ret_prd_infoList) {
		Ret_box ret_box = new Ret_box();
		String boxId = ret_prd_infoList.get(0).getBox_id_fk();
		for(int i=1; i< ret_prd_infoList.size();i++){
			if(!boxId.equals(ret_prd_infoList.get(i).getBox_id_fk())){
				gszMsgBuf = "请检查所有取消转入的产品，其箱号是否一致！";
				return new SimpleRtnBeen(E_XPCNPNLOUT_NOT_SAME_BOX);
			}
		}
		ret_box = retBoxDao.getWithLock(boxId, LockMode.UPGRADE);
		if (null == ret_box) {
			gszMsgBuf = new NotFoundRtnBeen(boxId, Ret_box.class).toString();
			return new SimpleRtnBeen(E_RET_BOX + E_READ_NOT_FOUND);
		}		

		if (!PROC_EMPTY.equals(ret_box.getBox_stat())) {
			gszMsgBuf = "箱子 [" + ret_box.getBox_id() + "] " + "的状态为 ["
					+ ret_box.getBox_stat() + "], " + ",必须是" + PROC_EMPTY
					+ "!";
			return new SimpleRtnBeen(E_XPCNPNLOUT_INVALID_BOX_STATUS);
		}

		if (WIP_REATIN.equals(ret_box.getBnk_flg())) {
			gszMsgBuf = "箱子的bnk_flg为 [" + ret_box.getBnk_flg()
				+ "],已在制保留，请先取消在制保留！";
			return new SimpleRtnBeen(E_XPCNPNLOUT_INVALIED_BNK_FLG);
		}
		
		if (!_YES.equals(ret_box.getValid_flg())) {
			gszMsgBuf = "箱子 [" + ret_box.getBox_id() + "] 无效!";
			return new SimpleRtnBeen(E_XPCNPNLOUT_BOX_INVALIED);
		}

		if (0 == ret_box.getPrd_qty()) {
			gszMsgBuf = "箱子 [" + ret_box.getBox_id()
					+ "] 的产品数量为 0";
			return new SimpleRtnBeen(E_XPCNPNLOUT_INVALIED_PRD_CNT);
		}

		return new SimpleRtnBeen(ret_box);
	}
	
	private long getPrdMode(String boxId) {
		long rtnCode = _NORMAL;
		Integer mode_cnt = 0;
		List<Ret_prd_info> ret_prd_infoList = new ArrayList<Ret_prd_info>();
		// Get prd info
		ret_prd_infoList = retPrdInfoDao.getShtListInfoWithLock(boxId);
		if(ret_prd_infoList != null){
			for(int i=0; i<ret_prd_infoList.size();i++){
				mode_cnt = mode_cnt + ret_prd_infoList.get(i).getX_axis_cnt_fk() * ret_prd_infoList.get(i).getY_axis_cnt_fk();
			}
		}
		outTrx.setMode_cnt(mode_cnt);
		return rtnCode;
	}
}
